#include <QtOpenGL/QtOpenGL>
#include <GL/glut.h>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QTimer>
#include "robotwidget.h"
#include "ui_robotwidget.h"
#include "model.h"

RobotWidget::RobotWidget(QWidget *parent)
    : QGLWidget(parent)
{
    fullscreen = false;
//    HWND hWND = (HWND)winId();                          //获取当前窗口句柄
//    m_HDC = GetDC(hWND);                                //通过窗口句柄获得HDC
}

RobotWidget::~RobotWidget()
{
    killFont();
}
void RobotWidget::initializeGL()                         //此处开始对OpenGL进行所以设置
{
    glClearColor(0.0, 0.0, 0.0, 0.0);                   //黑色背景
    glShadeModel(GL_SMOOTH);                            //启用阴影平滑

    glClearDepth(1.0);                                  //设置深度缓存
    glEnable(GL_DEPTH_TEST);                            //启用深度测试
    glDepthFunc(GL_LEQUAL);                             //所作深度测试的类型
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //告诉系统对透视进行修正
    GLfloat LightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f};  //环境光参数
    GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};  //漫散光参数
    GLfloat LightPosition[] = {-10.0f, 5.0f, -20.0f, 1.0f}; //光源位置
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);     //设置环境光
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);     //设置漫射光
    glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);   //设置光源位置
    glEnable(GL_LIGHT1);                                //启动一号光源
    buildFont();                                        //创建字体
}
void RobotWidget::resizeGL(int w, int h)                 //重置OpenGL窗口的大小
{
    glViewport(0, 0, (GLint)w, (GLint)h);               //重置当前的视口
    glMatrixMode(GL_PROJECTION);                        //选择投影矩阵
    glLoadIdentity();                                   //重置投影矩阵
    //设置视口的大小
    gluPerspective(45.0, (GLfloat)w/(GLfloat)h, 0.1, 100.0);
    glMatrixMode(GL_MODELVIEW);                         //选择模型观察矩阵
    glLoadIdentity();                                   //重置模型观察矩阵
}
void RobotWidget::paintGL()                              //从这里开始进行所以的绘制
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
    glLoadIdentity();                                   //重置当前的模型观察矩阵
    glTranslatef(0.0f, 0.0f, -20.0f);
    glRotated(-45.0f,0,1,0);
    glRotatef(m_xRot,1.0f,0.0f,0.0f);
    glRotatef(m_yRot,0.0f,1.0f,0.0f);
    glRotatef(m_zRot,0.0f,0.0f,1.0f);
    glPushMatrix();
    glPushMatrix();
    glTranslatef(0.0f,-5.0f,-1.75f);
    cube cu1{4.0f,0.05f,8.0f};
    creat (cu1,0.0f,1.0f,0.0f);
    glPopMatrix();
    glTranslatef(-0.5f,-4.95f,-0.5f);
    cylinder cy1{0.1f,0.1f,1.0f,10,10};
    creat(cy1,1.0f,1.0f,0.0f);
    glTranslatef(1.0f,0.0f,0.0f);
    creat(cy1,1.0f,1.0f,0.0f);
    glTranslatef(0.0f,0.0f,1.0f);
    creat(cy1,1.0f,1.0f,0.0f);
    glTranslatef(-1.0f,0.0f,0.0f);
    creat(cy1,1.0f,1.0f,0.0f);
    glPopMatrix();
    glPushMatrix();
    glTranslatef(0.0f,-3.95f,0.0f);
    cylinder cy2{1.5f,1.5f,0.75f,30,30};
    creat(cy2,1.0f,1.0f,0.0f);
    glTranslatef(-0.125f,1.0625f,-0.125f);
    glRotatef(joint1,0.0f,1.0f,0.0f);
    glPushMatrix();
    glTranslatef(0.7f,0.0f,0.0f);
    glRotatef(90.0f,1.0f,0.0f,0.0f);
    glRotatef(90.0f,0.0f,0.0f,1.0f);
    cylinder cy3{0.3125f,0.3125f,1.4f,30,30};
    creat(cy3,1.0f,1.0f,0.0f);
    glPopMatrix();
    glRotatef(joint2,1.0f,0.0f,0.0f);
    cube cu2{1.4f,1.55f,0.625f};
    creat(cu2,1.0f,1.0f,0.0f);
    glTranslatef(0.0f,1.55f,0.0f);
    glPushMatrix();
    glTranslatef(0.7f,0.0f,0.0f);
    glRotatef(90.0f,1.0f,0.0f,0.0f);
    glRotatef(90.0f,0.0f,0.0f,1.0f);
    creat(cy3,1.0f,1.0f,0.0f);
    glPopMatrix();
    glRotatef(joint3,1.0f,0.0f,0.0f);
    cube cu3{1.4f,2.425f,0.625f};
    creat(cu3,1.0f,1.0f,0.0f);
    glTranslatef(0.0f,2.425f,0.0f);
    glPushMatrix();
    glTranslatef(0.7f,0.0f,0.0f);
    glRotatef(90.0f,1.0f,0.0f,0.0f);
    glRotatef(90.0f,0.0f,0.0f,1.0f);
    creat(cy3,1.0f,1.0f,0.0f);
    glPopMatrix();
    glRotatef(joint4,1.0f,0.0f,0.0f);
    cube cu4{1.4f,1.0f,0.625f};
    creat(cu4,1.0f,1.0f,0.0f);
    glTranslatef(0.0f,0.0f,-0.625f);
    glPushMatrix();
    glTranslatef(0.0f,0.5f,0.0f);
    creat(cu4,1.0f,1.0f,0.0f);
    glPopMatrix();
    glTranslatef(-0.3f,1.5f,0.0f);
    cylinder cy4{0.45f,0.05f,30,30};
    creat(cy4,1.0f,1.0f,0.0f);
    glTranslatef(0.0f,0.05f,0.0f);
    glRotatef(joint5,0.0f,1.0f,0.0f);
    cube cu5{0.25,1.0f,0.25f};
    creat(cu5,1.0f,1.0f,0.0f);
    glTranslatef(((joint6*0.0015f)-3.125f),1.0f,0.0f);
    cube cu6{0.25f,1.5f,0.25f};
    creat(cu6,1.0f,1.0f,0.0f);
    glTranslatef(-2*((joint6*0.0015f)-3.125f),0.0f,0.0f);
    creat(cu6,1.0f,1.0f,0.0f);
    glPopMatrix();
    MyStatic sta;
    sta.GLxyz(-5,-5,-5.75,10);
  //  glColor3f(0.0f,0.0f, 1.0);
  //  glRasterPos3f(10,-5,-10);                      //设置光栅化位置，即字体位置
 //   glPrint("X");                                    //输出文字到屏幕上
}
void RobotWidget::buildFont()                            //创建位图字体
{
/*    HFONT font;                                         //字体句柄
        m_Base = glGenLists(96);                            //创建96个显示列表

        font = CreateFont(10,                       //字体高度
                          10,                                //字体宽度
                          0,                                //字体的旋转角度
                          0,                                //字体底线的旋转角度
                          FW_BOLD,                          //字体的重量
                          FALSE,                            //是否斜体
                          FALSE,                            //是否使用下划线
                          FALSE,                            //是否使用删除线
                          ANSI_CHARSET,                     //设置字符集
                          OUT_TT_PRECIS,                    //输出精度
                          CLIP_DEFAULT_PRECIS,              //剪裁精度
                          ANTIALIASED_QUALITY,              //输出质量
                          FF_DONTCARE | DEFAULT_PITCH,      //Family and Pitch的设置
                          LPCWSTR("Courier New"));          //字体名称(电脑中已装的)

        wglUseFontBitmaps(m_HDC, 32, 96, m_Base);           //创建96个显示列表，绘制ASCII码为32-128的字符
        SelectObject(m_HDC, font);                          //选择字体  */
}
void RobotWidget::killFont()                             //删除显示列表
{
//    glDeleteLists(m_Base, 96);                          //删除96个显示列表
}
void RobotWidget::glPrint(const char *fmt, ...)          //自定义输出文字函数
{
    char text[256];                                     //保存字符串
    va_list ap;                                         //指向一个变量列表的指针

    if (fmt == NULL)                                    //如果无输入则返回
    {
        return;
    }

    va_start(ap, fmt);                                  //分析可变参数
    vsprintf(text, fmt, ap);                        //把参数值写入字符串
    va_end(ap);                                         //结束分析

    glPushAttrib(GL_LIST_BIT);                          //把显示列表属性压入属性堆栈
    glListBase(m_Base - 32);                            //设置显示列表的基础值
    glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);  //调用显示列表绘制字符串
    glPopAttrib();                                      //弹出属性堆栈
}
void RobotWidget::keyPressEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case Qt::Key_F1:                                    //F1为全屏和普通屏的切换键
        fullscreen = !fullscreen;
        if (fullscreen)
        {
            showFullScreen();
        }
        else
        {
            showNormal();
        }
        break;
    case Qt::Key_Escape:                                //ESC为退出键
        close();
        break;
    case Qt::Key_L:                                     //L为开启关闭光源的切换键
        m_Light = !m_Light;
        if (m_Light)
        {
            glEnable(GL_LIGHTING);                      //开启光源
        }
        else
        {
            glDisable(GL_LIGHTING);                     //关闭光源
        }
        break;
    case Qt::Key_PageUp:
        joint1 -= 0.5f;
        break;
    case Qt::Key_PageDown:
        joint1 += 0.5f;
        break;
    case Qt::Key_Up:
        joint2 += 0.5f;
        break;
    case Qt::Key_Down:
        joint2 -= 0.5f;
        break;
    case Qt::Key_Right:
        joint3 +=0.5f;
        break;
    case Qt::Key_Left:
        joint3 -= 0.5f;
        break;
    case Qt::Key_W:
        joint4 += 0.5f;
        break;
    case Qt::Key_S:
        joint4 -= 0.5f;
        break;
    case Qt::Key_A:
        joint5 -= 0.5f;
        break;
    case Qt::Key_D:
        joint5 += 0.5f;
        break;
    case Qt::Key_O:
        joint6 +=0.1f;
        break;
    case Qt::Key_P:
        joint6 -=0.1f;
        break;

    }
    updateGL();
}

static void qNormalizeAngle(int &angle)
{
    while (angle < 0)
        angle += 360;
    while (angle > 360 )
        angle -= 360;
}

void RobotWidget::setXRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != m_xRot) {
        m_xRot = angle;
        update();
    }
}

void RobotWidget::setYRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != m_yRot) {
        m_yRot = angle;
        update();
    }
}

void RobotWidget::setZRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != m_zRot) {
        m_zRot = angle;
        update();
    }
}

void RobotWidget::mousePressEvent(QMouseEvent *event)
{
    m_lastPos = event->pos();
//    qDebug()<<m_xRot<<m_yRot<<m_zRot;
}

void RobotWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - m_lastPos.x();
    int dy = event->y() - m_lastPos.y();

    if (event->buttons() & Qt::LeftButton) {
        setXRotation(m_xRot + dy);
        setYRotation(m_yRot + dx);
    } else if (event->buttons() & Qt::RightButton) {
        setXRotation(m_xRot + dy);
        setZRotation(m_zRot + dx);
    }
    m_lastPos = event->pos();
}
